package com.googlecode.grima.service;

import java.util.List;

import org.activiti.engine.IdentityService;
import org.apache.commons.lang.StringUtils;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.googlecode.grima.base.GenericDao;
import com.googlecode.grima.base.GenericEntityService;
import com.googlecode.grima.base.GenericEntityServiceImpl;
import com.googlecode.grima.base.Page;
import com.googlecode.grima.base.SearchResult;
import com.googlecode.grima.base.SearchTemplate;
import com.googlecode.grima.dao.UserDao;
import com.googlecode.grima.domain.User;

@Service("userService")
public class UserService extends GenericEntityServiceImpl<User, Long> implements GenericEntityService<User, Long> {

	public static final String DEFAULT_PASSWORD = "grima";
	
	protected UserDao userDao;
	protected IdentityService identityService;
	protected GroupService groupService;

	@Autowired
	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	@Autowired
	public void setIdentityService(IdentityService identityService) {
		this.identityService = identityService;
	}

	@Autowired
	public void setGroupService(GroupService groupService) {
		this.groupService = groupService;
	}
	
	@Override
	public GenericDao<User, Long> getDao() {
		return userDao;
	}

	@Override
	public User getNew() {
		return new User();
	}

	@Override
	public User getNewWithDefaults() {
		return getNew();
	}
	
	@Override
	@Transactional
	public void save(User user) {
		org.activiti.engine.identity.User activitiUser = identityService.createUserQuery().userId(user.getLogin()).singleResult();
		if (activitiUser == null){
			activitiUser = identityService.newUser(user.getLogin());
		}
		
		activitiUser.setEmail(user.getEmail());
		activitiUser.setFirstName(user.getFirstName());
		activitiUser.setLastName(user.getLastName());
		
		if (StringUtils.isEmpty(user.getPassword())){
			user.setPassword(DEFAULT_PASSWORD);
		}
		activitiUser.setPassword(user.getPassword());
		identityService.saveUser(activitiUser);

		createMembership(user.getLogin(), user.getGroups());
		
		super.save(user);
	}
	
	private void createMembership(String login, String[] groups) {
		removeMembership(login);
		if (groups != null){
			for (String group : groups) {
					identityService.createMembership(login, group);
			}
		}
  }

	private void removeMembership(String login) {
		String[] userGroups = groupService.findUserGroups(login);
		for (String group : userGroups) {
	    identityService.deleteMembership(login, group);
    }
  }

	public SearchResult<User, Long> findAll(Page page){
		SearchResult<User, Long> ret = new SearchResult<User, Long>();
		
		SearchTemplate searchTemplate = new SearchTemplate();
		
		if (page != null) {
			int pageNumber = page.getPageNumber();
			int pageSize = page.getPageSize();
    	int firstResult = ((pageNumber-1) * pageSize);
    	searchTemplate.setFirstResult(firstResult);
    	searchTemplate.setMaxResults(pageSize);
		}

		List<User> users = find(searchTemplate);
		int count = findCount(searchTemplate);
		fillUsersData(users);

		ret.setTotal(count);
		ret.setRows(users);
		
		return ret;
	}
	
	public User findById(Long id){
		User user = getByPrimaryKey(id);
		if (user != null){
			fillUserData(user);
		}
		return user;
	}
	
	public User findByLogin(String login){
		User ret = null;
		SearchTemplate searchTemplate = new SearchTemplate();
		searchTemplate.addCriterion(Restrictions.like("login", login));
		List<User> users = find(searchTemplate);
		if (users != null && users.size() > 0){
			ret = users.get(0);
			fillUserData(ret);
		}
		return ret;
	}
	
	public SearchResult<User, Long> findByParameters(String firstName, String lastName, String login, String email, Page page) {
		SearchResult<User, Long> ret = new SearchResult<User, Long>();
		
    SearchTemplate searchTemplate = new SearchTemplate();

    if (page != null){
    	int pageNumber = page.getPageNumber();
			int pageSize = page.getPageSize();    
			int firstResult = ((pageNumber-1) * pageSize);
			
			searchTemplate.setFirstResult(firstResult);
			searchTemplate.setMaxResults(pageSize);
    }

    if (StringUtils.isNotEmpty(firstName)){
    	searchTemplate.addCriterion(Restrictions.like("firstName", "%"+firstName+"%"));
    }

    if (StringUtils.isNotEmpty(lastName)){
    	searchTemplate.addCriterion(Restrictions.like("lastName", "%"+lastName+"%"));
    }

    if (StringUtils.isNotEmpty(login)){
    	searchTemplate.addCriterion(Restrictions.like("login", "%"+login+"%"));
    }

    if (StringUtils.isNotEmpty(email)){
    	searchTemplate.addCriterion(Restrictions.like("email", "%"+email+"%"));
    }

		List<User> users = find(searchTemplate);
		int count = findCount(searchTemplate);
		fillUsersData(users);

		ret.setTotal(count);
		ret.setRows(users);
		
		return ret;
  }
	
	private void fillUsersData(List<User> users){
		for (User user : users) {
			fillUserData(user);
		}
	}

	private void fillUserData(User user){
		String[] groups = groupService.findUserGroups(user.getLogin());
		user.setGroups(groups);
	}

	public void deleteById(Long id){
		User user = getByPrimaryKey(id);
		deleteByPrimaryKey(id);
		identityService.deleteUser(user.getLogin());
	}

}
